package com.xuecheng.auth.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;

import javax.annotation.Resource;


 @Configuration
 @EnableAuthorizationServer
  public class AuthorizationServer extends AuthorizationServerConfigurerAdapter {

  @Resource(name="authorizationServerTokenServicesCustom")
  private AuthorizationServerTokenServices authorizationServerTokenServices;

 @Autowired
 private AuthenticationManager authenticationManager;

 //客户端详情服务  这是OAuth2的配置 用户点击授权以后需要认证服务进行颁发令牌
 //这是认证服务 也就是客户端需要请求认证服务进行获取授权码 这里就是下发授权码的操作
  @Override
  public void configure(ClientDetailsServiceConfigurer clients)
          throws Exception {
        clients.inMemory()// 使用in-memory存储
                .withClient("XcWebApp")// client_id 客户端id 与浏览器发出的请求保持一致 也就是在测试里面可以对比一下
//                .secret("XcWebApp")//客户端密钥
                .secret(new BCryptPasswordEncoder().encode("XcWebApp"))//客户端密钥 改成经过BCryptPasswordEncoder加密的
                .resourceIds("xuecheng-plus")//资源列表
                .authorizedGrantTypes("authorization_code", "password","client_credentials","implicit","refresh_token")// 该client允许的授权类型authorization_code,password,refresh_token,implicit,client_credentials
                .scopes("all")// 允许的授权范围
                .autoApprove(false)//false跳转到授权页面  这步就是流程中的浏览器打开二维码 用户也就是资源拥有者进行扫码后请求认证服务进行返回认证的确认页面
                //客户端接收授权码的重定向地址  这步就是用户同意授权后把授权码下发到网址也就是客户端
                .redirectUris("http://www.51xuecheng.cn")
   ;
  }
  //POST {{auth_host}}/auth/oauth/token?client_id=XcWebApp&client_secret=XcWebApp&grant_type=authorization_code&code=D7IDmM&redirect_uri=http://www.51xuecheng.cn
  //然后在测试里面 客户端就可以拿着上面返回的授权码再次到认证服务获取令牌

 //密码模式
 //POST {{auth_host}}/auth/oauth/token?client_id=XcWebApp&client_secret=XcWebApp&grant_type=password&username={"username":"stu1","authType":"password","password":"111111"}
 //且在username里面对参数进行了拓展 则jwt令牌携带的信息就会变得更多了


  //令牌端点的访问配置  这是和资源服务也就是微服务进行端对端的匹配的 资源服务里面有一个配置类ResourceServerConfig对应起来
  //这是认证服务 用来配置令牌（token）的访问端点和令牌服务（token service）
  @Override
  public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
   endpoints
           //告诉 Spring Security OAuth2 如何进行用户认证。这通常是一个 AuthenticationManager 对象，用于验证用户的身份。
           //这里也是和Spring Security进行关联的吧
           .authenticationManager(authenticationManager)//认证管理器
           //JWT 令牌里包含的用户信息和权限通常是从 loadUserByUsername 方法返回的 UserDetails 对象中获取的。
           //将配置好的令牌管理服务应用到授权服务器端点，使得在用户登录成功后，Spring Security OAuth2 能够自动调用令牌管理服务生成 JWT 令牌，并将其返回给客户端
           .tokenServices(authorizationServerTokenServices)//令牌管理服务
           .allowedTokenEndpointRequestMethods(HttpMethod.POST);
  }

  //令牌端点的安全配置 用来配置令牌的安全约束
  @Override
  public void configure(AuthorizationServerSecurityConfigurer security){
   security
           .tokenKeyAccess("permitAll()")                    //oauth/token_key是公开
           .checkTokenAccess("permitAll()")                  //oauth/check_token公开
           .allowFormAuthenticationForClients()				//表单认证（申请令牌）
   ;
  }

 //TokenConfig为令牌策略配置类

 }
